<?php

/**
 * Erra_Core_DatabasePdo - PHP5 database object manager
 *
 * @package
 * @author Alexis Eric
 * @copyright Copyright (c) 2012 - Erra Prod
 * @version $1.0$
 * @access public
 */
class Erra_Core_DatabasePdo extends PDO {

    public static $dbSingleton = null;
    private static $queryStack = array();
    private $queryString;

    /**
     * Erra_Core_DatabasePdo::getSingleton() - Returns database singleton
     *
     * @return
     */
    public static function getSingleton() {
        if (is_null(self::$dbSingleton)) {
            self::dbConnect();
        }
        return self::$dbSingleton;
    }

    public static function dbInit($DB_DRIVER, $DB_HOST, $DB_NAME, $DB_USER, $DB_PASSWORD) {
        try {
            self::$dbSingleton = new Erra_Core_DatabasePdo($DB_DRIVER . ':host=' . $DB_HOST . ';dbname=' . $DB_NAME, $DB_USER, $DB_PASSWORD);
        } catch (Exception $e) {
            Erra_Core_Kernel::fatalError($e);
        }
    }

    public static function dbConnect() {
        try {
            self::$dbSingleton = new Erra_Core_DatabasePdo(config_get('database.db_driver') . ':host=' . config_get('database.db_host') . ';dbname=' . config_get('database.db_name'), config_get('database.db_user'), config_get('database.db_password'));
        } catch (Exception $e) {
            Erra_Core_Kernel::fatalError(__("Can't establish connection to database. Check connection parameters in `" . INI_FILE . "` file. <br/><br/>Framework throwns exception : ") . $e);
        }
    }

    public static function interpolateQuery($query, $params) {
        $keys = array();

        # build a regular expression for each parameter
    
        foreach ($params as $key => $value) {
            $params[$key] = '"'.$value.'"';
            if (is_string($key)) {
                $keys[] = '/:' . $key . '/';
            } else {
                $keys[] = '/[?]/';
            }
        }

        $query = preg_replace($keys, $params, $query, 1, $count);

        #trigger_error('replaced '.$count.' keys');

        return $query;
    }

    public static function SELECT($query) {
        if (is_null(self::$dbSingleton)) {
            self::dbConnect();
        }
        self::$dbSingleton->queryString = $query;
        $queryResult = self::$dbSingleton->query($query);
        if (is_object($queryResult)) {
            $queryResult->setFetchMode(PDO::FETCH_OBJ);
        }
        return $queryResult;
    }

    public static function _SELECT($query) {
        if (is_null(self::$dbSingleton)) {
            self::dbConnect();
        }

        self::$dbSingleton->queryString = $query;

        $time_start = microtime_float();
        $queryResult = self::$dbSingleton->query($query);
        if (is_object($queryResult)) {
            $queryResult->setFetchMode(PDO::FETCH_ASSOC);
        }
        $time_end = microtime_float();
        $time = ($time_end - $time_start) * 1000;
        if ($queryResult == FALSE) {
            Erra_Core_Kernel::log(__('[Erra_Core_DatabasePdo] : Error while trying to execute SELECT request : `') . $query . '`');
        } else {
            self::$queryStack[] = array('query' => $query, 'execution_time' => (float) $time);
        }
        return $queryResult;
    }

    public static function EXECUTE($query, $placeHolders = null) {
        if (is_null(self::$dbSingleton)) {
            self::dbConnect();
        }

        $originalQuery = $query;
        $time_start = microtime_float();
        $query = self::$dbSingleton->prepare($query);
        if (!is_null($placeHolders) && is_array($placeHolders)) {
            $result = $query->execute($placeHolders);
        } else {
            $result = $query->execute();
        }
        $time_end = microtime_float();
        $time = ($time_end - $time_start) * 1000;
        if ($result == FALSE) {
            Erra_Core_Kernel::log(__('[Erra_Core_DatabasePdo] : Error while executing SQL statement: `') . self::interpolateQuery($query->queryString, $placeHolders) . '`');
        } else {
            self::$queryStack[] = array('query' => $query, 'execution_time' => (float) $time);
        }
        return $result;
    }

    public static function LAST_INSERT_ID() {
        if (is_null(self::$dbSingleton)) {
            self::dbConnect();
        }
        return self::$dbSingleton->lastInsertId();
    }

    public static function rowCount() {
        if (is_null(self::$dbSingleton)) {
            self::dbConnect();
        }
        $regex = '/^SELECT\s+(?:ALL\s+|DISTINCT\s+)?(?:.*?)\s+FROM\s+(.*)$/i';
        if (preg_match($regex, self::$dbSingleton->queryString, $output) > 0) {
            $stmt = self::$dbSingleton->query("SELECT COUNT(*) FROM {$output[1]}", PDO::FETCH_NUM);
            return is_object($stmt) ? $stmt->fetchColumn() : false;
        }
        return false;
    }

    public static function logQueries() {
        if (config_get('debug.log_messages') == 1) {
            $totalQueries = count(self::$queryStack);
            $totalExecutionTime = 0.0;
            if ($totalQueries > 0) {
                $firephp = FirePHP::getInstance(true);
                foreach (self::$queryStack as $query_item) {
                    $totalExecutionTime+=$query_item['execution_time'];
                }
                $firePhpSqlTable = array();
                $firePhpSqlTable[] = array('Execution time', 'Query');

                foreach (self::$queryStack as $query_item) {
                    $firePhpSqlTable[] = array(sprintf("%.3f", $query_item['execution_time']), $query_item['query']);
                }
                $stringQuery = ($totalQueries == 1) ? $totalQueries . ' query' : $totalQueries . ' queries';
                if (config_get('debug.firebug_lite')) {
                    Erra_Core_Kernel::log($stringQuery . ' executed in ' . sprintf("%.3f", $totalExecutionTime) . ' ms', 'info');
                } else {
                    $firephp->table($stringQuery . ' executed in ' . sprintf("%.3f", $totalExecutionTime) . ' ms', $firePhpSqlTable);
                }
            }
        }
    }

}

?>